package com.yuxer.mybatisplus.utils;


import cn.hutool.core.util.StrUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.regex.Pattern.compile;

/**
 * @author zyc
 * @version 1.0
 * @since 2021/3/17 21:15
 */
public class StrUtils {
    /**
     * 营业执照常用代码集
     */
    private static final String BASE_CODE_STRING = "0123456789ABCDEFGHJKLMNPQRTUWXY";
    private static final char[] BASE_CODE_ARRAY = BASE_CODE_STRING.toCharArray();
    private static final List<Character> BASE_CODES = new ArrayList<>();
    private static final String BASE_CODE_REGEX = "[" + BASE_CODE_STRING + "]{18}";
    private static final int[] WEIGHT = {1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28};

    static {
        for (char c : BASE_CODE_ARRAY) {
            BASE_CODES.add(c);
        }
    }

    /**
     * 是有效的身份证号
     *
     * @param idCard 身份证号
     * @return true-有效 false-无效
     */
    public static boolean isValidIdCard(String idCard) {
        if (isEmpty(idCard)) {
            return false;
        }
        String id = idCard.toUpperCase();
        // 18位身份证号码的格式为6位地址码 + 8位生日 + 3位顺序码 + 1位校验码
        String regex = "^\\d{17}[\\dX]$";
        if (!id.matches(regex)) {
            return false;
        }
        // 权重因子
        int[] weights = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        // 校验数组
        char[] codes = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
        // 校验码计算
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += (id.charAt(i) - '0') * weights[i];
        }
        int index = sum % 11;
        return id.charAt(17) == codes[index];
    }

    /**
     * 反向取值-是否是非法身份证号
     *
     * @param idCard 身份证号
     * @return true-无效 false-有效
     */
    public static boolean isNotValidIdCard(String idCard) {
        return !isValidIdCard(idCard);
    }

    /**
     * 根据身份证号获取性别
     *
     * @param idCard 身份证还
     * @return 性别文字
     */
    public static String getGender(String idCard) {
        if (!isValidIdCard(idCard)) {
            throw new IllegalArgumentException("无效的身份证号码");
        }
        int genderCode = Integer.parseInt(idCard.substring(16, 17));
        if (genderCode % 2 == 0) {
            return "女";
        } else {
            return "男";
        }
    }

    /**
     * 是有效的统一社会信用代码
     *
     * @param socialCreditCode 统一社会信用代码
     * @return 是否是
     */
    public static boolean isValidSocialCreditCode(String socialCreditCode) {
        if (isEmpty(socialCreditCode) || !Pattern.matches(BASE_CODE_REGEX, socialCreditCode)) {
            return false;
        }
        char[] businessCodeArray = socialCreditCode.toCharArray();
        char check = businessCodeArray[17];
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            char key = businessCodeArray[i];
            sum += (BASE_CODES.indexOf(key) * WEIGHT[i]);
        }
        int value = 31 - sum % 31;
        return check == BASE_CODE_ARRAY[value % 31];
    }

    /**
     * 不是有效的统一社会信用代码
     *
     * @param socialCreditCode 统一社会信用代码
     * @return true-不是
     */
    public static boolean isNotValidSocialCreditCode(String socialCreditCode) {
        return !isValidSocialCreditCode(socialCreditCode);
    }

    /**
     * 判空
     *
     * @param str 字符串
     * @return 是否为空
     */
    public static boolean isEmpty(String str) {
        if (StrUtil.isEmpty(str)) {
            return true;
        }
        return removeSpace(str).isEmpty();
    }

    /**
     * 非空
     *
     * @param str 字符串
     * @return 是否为空
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

    /**
     * 判断字符串是不是合格的手机号
     *
     * @param phone 手机号字符串
     * @return 是否是
     */
    public static boolean isPhone(String phone) {
        if (isEmpty(phone)) {
            return false;
        }
        // 使用正则表达式匹配手机号码格式
        String regex = "^(?:(?:\\+|00)86)?1[3-9]\\d{9}$";
        // 进行匹配
        Pattern pattern = Pattern.compile(regex);
        return pattern.matcher(phone).matches();
    }

    public static boolean isNotPhone(String phone) {
        return !isPhone(phone);
    }

    /**
     * 判断字符串是否是数字
     *
     * @param str 字符串
     * @return 是否是
     */
    public static boolean isNum(String str) {
        try {
            Double.parseDouble(str);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    public static boolean isNotNum(String str) {
        return !isNum(str);
    }

    /**
     * 检查字符串是否是条形码
     *
     * @param barCode 字符串
     * @return 是否是条形码
     */
    public static boolean isBarCode(String barCode) {
        if (isEmpty(barCode)) {
            return false;
        }
        return isNum(barCode);
    }

    public static boolean isNotBarCode(String barCode) {
        return !isBarCode(barCode);
    }

    /**
     * 消除字符串里所有的空格、制表符、换行符、回车
     *
     * @param str 欲修改字符串
     * @return 完成后的字符串，如果传入是null，则会返回一个""
     */
    public static String removeSpace(String str) {
        if (str == null) {
            return "";
        }
        return compile("\\s*").matcher(str).replaceAll("");
    }

    /**
     * 把中文括号换成英文括号
     *
     * @param str 需要替换的字符串
     * @return 结果
     */
    public static String replaceBrackets(String str) {
        return str.replace("（", "(").replace("）", ")");
    }

    /**
     * 把中文分号换成英文分号
     *
     * @param str 需要替换的字符串
     * @return 结果
     */
    public static String replaceSemicolon(String str) {
        return str.replace("；", ";");
    }

    /**
     * 字符串转数字
     *
     * @param str 字符串
     * @return 数字
     */
    public static int strToInt(String str) {
        try {
            return Integer.parseInt(str);
        } catch (Exception e) {
            return -1;
        }
    }

    /***
     * 匹配
     * 根据字符和正则表达式进行匹配
     *
     * @param str 源字符串
     * @param regex 正则表达式
     *
     * @return true：匹配成功  false：匹配失败
     */
    private static boolean match(String str, String regex) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        return matcher.find();
    }

    /**
     * 字符串是否包含中文(只检查汉字)
     *
     * @param str 待校验字符串
     * @return true 包含中文字符 false 不包含中文字符
     */
    public static boolean isContainChinese(String str) {
        if (isEmpty(str)) {
            return false;
        }
        return match(str, "[\u4e00-\u9fa5]");
    }

    public static boolean isNotContainChinese(String str) {
        return !isContainChinese(str);
    }

    /**
     * 字符串是否包含中文（检查汉字和中文标点符号）
     *
     * @param str 待校验字符串
     * @return true 包含中文字符 false 不包含中文字符
     */
    public static boolean isContainChineseCharacter(String str) {
        if (isEmpty(str)) {
            return false;
        }
        return match(str, "[\u4E00-\u9FA5|\\！|\\，|\\。|\\（|\\）|\\《|\\》|\\“|\\”|\\？|\\：|\\；|\\【|\\】]");
    }

    public static boolean isNotContainChineseCharacter(String str) {
        return !isContainChineseCharacter(str);
    }
}
